package Dungeoneering.api.wrappers;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;

import org.powerbot.game.api.methods.Game;
import org.powerbot.game.api.methods.interactive.NPCs;
import org.powerbot.game.api.methods.node.GroundItems;
import org.powerbot.game.api.util.Filter;
import org.powerbot.game.api.wrappers.Tile;
import org.powerbot.game.api.wrappers.interactive.NPC;
import org.powerbot.game.api.wrappers.node.GroundItem;
import org.powerbot.game.api.wrappers.node.SceneObject;

import Dungeoneering.Entities.Room;
import Dungeoneering.api.methods.Objects;

/**
 * Every room has its own area of tiles. We define that area so we can very easely gather a list of all the objects, npcs,... inside the room
 * @author Nicolaas
 *
 */
public class TileArea {
	
	private final Tile[] tiles;
	private final Room parent;
	
	/**
	 * Instantiates a new TileArea
	 * 
	 * @param parent the room that has this area
	 * @param tiles the tiles that form the area
	 */
	public TileArea(Room parent, Tile[] tiles) {
		this.tiles = tiles;
		this.parent = parent;
	}
	
	/**
	 * gets the room that is linked to this area
	 * @return the parent room
	 */
	public Room getRoom() {
		return parent;
	}
	
    /**
     * Contains location.
     *
     * @param x the x
     * @param y the y
     * @return true, if successful
     */
	public boolean contains(int x, int y) {
		return this.contains(new Tile(x, y, Game.getPlane()));
	}
	
    /**
     * Contains Tiles.
     *
     * @param tiles the tiles
     * @return true, if successful
     */
    public boolean contains(Tile... tiles) {
        Tile[] areaTiles = this.getTileArray();
        for (Tile check : tiles) {
            for (Tile space : areaTiles) {
                if (check.equals(space)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    /**
     * Gets the tile array.
     *
     * @return the tile array
     */
    public Tile[] getTileArray() {
        return tiles;
    }
    
    /**
     * Checks whether the entire Area (in this case room) is loaded to avoid mistakes
     * @return true if loaded
     */
    public boolean isCompletelyLoaded() {
    	// matrix, so first one should be at [0,0] and last one at [x, y]
    	return tiles[0] != null && tiles[tiles.length - 1] != null;
    }
    
    /**
     * Gets a list of Npc's that are loaded in this area
     * 
     * @return the list of npc's loaded in the area
     */
    public ArrayList<NPC> getNpcs() {
    	return new ArrayList<NPC>(Arrays.asList(NPCs.getLoaded(new Filter<NPC>() {

			@Override
			public boolean accept(NPC n) {
				return contains(n.getLocation());
			}
		})));
    }
    
    public LinkedHashMap<Point, SceneObject[]> getLocations() {
    	LinkedHashMap<Point, SceneObject[]> returnValue = new LinkedHashMap<Point, SceneObject[]>();
    	for (Tile t : tiles) {
    		returnValue.put(new Point(t.getX(), t.getY()), Objects.getLoaded(t));
    	}
    	return returnValue;
    }
    
    public HashMap<Point, GroundItem[]> getItems() {
    	HashMap<Point, GroundItem[]> returnValue = new HashMap<Point, GroundItem[]>();
    	for (Tile t : tiles) {
    		returnValue.put(new Point(t.getX(), t.getY()), GroundItems.getLoadedAt(t.getX(), t.getY()));
    	}
    	return returnValue;
    }
}
